﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.TestModels.Northwind;

namespace Microsoft.EntityFrameworkCore.Query;

#nullable disable

public abstract class NorthwindKeylessEntitiesQueryRelationalTestBase<TFixture>(TFixture fixture)
    : NorthwindKeylessEntitiesQueryTestBase<TFixture>(fixture)
    where TFixture : NorthwindQueryFixtureBase<NoopModelCustomizer>, new()
{
    [ConditionalTheory]
    [MemberData(nameof(IsAsyncData))]
    public virtual async Task Projecting_collection_correlated_with_keyless_entity_throws(bool async)
    {
        var message = (await Assert.ThrowsAsync<InvalidOperationException>(
            () => AssertQuery(
                async,
                ss => ss.Set<CustomerQuery>().Select(
                    cq => new
                    {
                        cq.City,
                        cq.CompanyName,
                        OrderDetailIds = ss.Set<Customer>().Where(c => c.City == cq.City).ToList()
                    }).OrderBy(x => x.City).Take(2)))).Message;

        Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message);
    }

    [ConditionalTheory]
    [MemberData(nameof(IsAsyncData))]
    public virtual async Task Collection_of_entities_projecting_correlated_collection_of_keyless_entities(bool async)
    {
        var message = (await Assert.ThrowsAsync<InvalidOperationException>(
            () => AssertQuery(
                async,
                ss => ss.Set<Customer>().OrderBy(c => c.CustomerID).Select(
                    c => new
                    {
                        c.City, Collection = ss.Set<CustomerQuery>().Where(cq => cq.City == c.City).ToList(),
                    })))).Message;

        Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message);
    }

    public override async Task KeylessEntity_with_included_navs_multi_level(bool async)
    {
        var message = (await Assert.ThrowsAsync<InvalidOperationException>(
            () => base.KeylessEntity_with_included_navs_multi_level(async))).Message;

        Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message);
    }

    public override async Task KeylessEntity_with_defining_query_and_correlated_collection(bool async)
    {
        var message = (await Assert.ThrowsAsync<InvalidOperationException>(
            () => base.KeylessEntity_with_defining_query_and_correlated_collection(async))).Message;

        Assert.Equal(RelationalStrings.InsufficientInformationToIdentifyElementOfCollectionJoin, message);
    }

    protected override QueryAsserter CreateQueryAsserter(TFixture fixture)
        => new RelationalQueryAsserter(
            fixture, RewriteExpectedQueryExpression, RewriteServerQueryExpression);
}
